using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.ComponentModel.Design.Serialization;
using System.CodeDom;
using GuavaData;

namespace GuavaLib
{
    [DesignerSerializer(typeof(GLaunchControlSerializer<GButton>),
        typeof(CodeDomSerializer))]
    public partial class GButton : Button, Guava, GuavaLaunchBase
    {
        string gname;
        string strLaunchFile;
        Type s;

        public GButton()
        {
            InitializeComponent();
            this.Click += new EventHandler(btnThis_Click);
        }
        
        #region Guava Members

        public LaunchType LType
        {
            get
            {
                return LaunchType.Single;
            }
        }

        public ControlType CType
        {
            get
            {
                return ControlType.None;
            }
        }

        public string GText
        {
            get
            {
                return this.Text;
            }
        }

        public string GName
        {
            get
            {
                if (gname == null) return this.Name;
                return gname;
            }
            set
            {
                gname = value;
            }
        }

        public Point GLocation
        {
            get { return this.Location; }
        }

        public Size GSize
        {
            get { return this.Size; }
        }

        public List<Guava> GComponents
        {
            get
            {
                List<Guava> lg = new List<Guava>();
                if (s == null) return lg;

                ConstructorInfo ci = s.GetConstructor(new Type[] { });
                Object o = ci.Invoke(new object[] { });
                lg.Add(o as Guava);

                return lg;
            }
        }

        public void GBind(string table, int i)
        {
            return;
        }

        public string GDefault
        {
            get { return null; }
        }

        public string GToolTip
        {
            get
            {
                Control p = this.TopLevelControl;
                if (!(p is Guava)) return null;
                ToolTip t = (p as GuavaForm).GToolTipProvider;
                if (t == null) return null;

                // Fetch the tooltip and return it
                return t.GetToolTip(this);
            }
        }

        public GuavaData.Domain.Domain GDomain
        {
            get
            {
                return null;
            }
        }

        public Guava this[string s]
        {
            get
            {
                foreach (Guava g in this.GComponents) if (g.GName == s) return g;
                return null;
            }
        }
        #endregion

        [Editor(typeof(GUIFilenameEditor), typeof(System.Drawing.Design.UITypeEditor))]
        public string GLaunchType
        {
            get
            {
                return strLaunchFile;
            }

            set
            {
                strLaunchFile = value;
            }
        }
        
        public Type Launch
        {
            get
            {
                return s;
            }

            set
            {
                this.s = value;
            }
        }

        public Type GetLaunchType()
        {
            if ((null == s) && strLaunchFile.Length > 0)
            {
                s = GLaunchClass.RetrieveTypeFromFile(strLaunchFile, Assembly.GetCallingAssembly());
            }
            return s;
        }

        private void btnThis_Click(object sender, EventArgs e)
        {
            // Get parent form
            Control p = this.TopLevelControl;
            if (!(p is Guava)) return;
            GuavaForm pForm = p as GuavaForm;
            this.PrepareStackFrame();
            this.LaunchForm(pForm.ID, null, false);
        }

        #region GuavaLaunchBase Members

        public DialogResult LaunchForm(Guid gid, string form, bool bNew)
        {
            if (s == null) return DialogResult.Cancel;

            // Get parent form
            Control p = this.TopLevelControl;
            if (!(p is Guava)) return DialogResult.Cancel;

            ConstructorInfo ci = s.GetConstructor(new Type[] { typeof(Guid), typeof(Guid), typeof(bool), typeof(GSeed) });
            GForm o = ci.Invoke(new object[] { gid, gid, bNew, (p as GuavaForm).GS }) as GForm;
            return o.ShowDialog();
        }

        public void PrepareStackFrame()
        {
            // Build the seed stack frame call list
            GuavaForm gForm = this.TopLevelControl as GuavaForm;
            GSeed gsTemp = gForm.GS;
            GSeedFrame gsfTemp = gsTemp.Peek();

            // Create a list of controls
            Control p = this;
            Control q = p.Parent;
            List<string> ls = new List<string>();
            ls.Add(this.GName);

            // Follow parents up the chain to the root form
            while (!(q is GuavaForm))
            {
                if (!(q is Guava))
                {
                    Guava r = q.Parent as Guava;
                    if (r == null) throw new Exception("Found two non-guava objects nested together in the same tree for marking.");
                    bool bfound = false;
                    foreach (Guava g in r.GComponents)
                    {
                        if (g.GComponents.Contains(p as Guava))
                        {
                            ls.Insert(0, g.GName);
                            bfound = true;
                            break;
                        }
                    }
                    if (!bfound) throw new Exception("Could not match a guava object for creating a seed for marking.");
                }
                else ls.Insert(0, (q as Guava).GName);
                p = p.Parent;
                q = q.Parent;
            }
            gsfTemp.controls = ls;
        }

        public void SetObject(Guid id)
        {
            return;
        }

        #endregion
    }
}
